class SinglyLinkedList {

    constructor() {
        this.numberNode = 0;
        this.head = null;
        this.tail = null;
    }

    add(val) {
        let node = new LinkedNode(val);
        if (!this.head) {
            this.head = node;
            this.tail = node;
        } else {
            this.tail.next = node;
            this.tail = node;
        }
        this.numberNode ++;
    }

    insertAfter(val, targetVal) {
        let node = this.find(targetVal);
        if (!node) return;
        let newNode = new LinkedNode(val);
        newNode.next = node.next;
        node.next = newNode;
        if (this.tail === node) {
            this.tail = newNode;
        }
        this.numberNode ++;
    }

    remove(val) {
        let pre = this.head;
        let node = this.head;
        while (node) {
            if (node.val === val) {
                if (this.head === node) {
                    this.head = this.head.next;
                }

                if (this.tail === node) {
                    this.tail = pre;
                }

                pre.next = node.next;
                this.numberNode --;
            } else {
                pre = node;
            }
            node = node.next;
        }
    }

    find(val) {
        let node = this.head;
        while (node) {
            if (node.val === val) {
                return node;
            } else {
                node = node.next;
            }
        }
        return node;
    }

    traverse(fn) {
        let node = this.head;

        while (node) {
            fn(node);
            node = node.next;
        }
    }

    length() {
        return this.numberNode;
    }

    toString() {
        let str = "";
        let node = this.head;

        while (node) {
            str += node.val + " ";
            node = node.next;
        }

        return str;
    }

    print() {
        console.log(this.toString())
    }
}

class LinkedNode {
    constructor(val) {
        this.val = val;
        this.next = null;
    }
}

exports.SinglyLinkedList = SinglyLinkedList;